package checkers.businessLogic;

import checkers.businessLogic.entity.GameTable;
import checkers.exceptions.EmailNotFoundException;
import checkers.businessLogic.game.Game;
import checkers.businessLogic.game.GameListener;
import checkers.businessLogic.game.Position;
import checkers.constants.web.SessionAttributes;
import checkers.database.MySQLGameOperations;
import checkers.database.MySQLUserOperations;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;

/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */
/**
 *
 * @author artinshahverdian
 */
public class GameManager implements GameListener {

    private LinkedList<Game> games = new LinkedList<Game>();
    private static GameManager instance = null;
    MySQLGameOperations mySqlGameOperations = null;
    MySQLUserOperations mySQLUserOperations = null;

    private GameManager() throws Exception {

        mySqlGameOperations = MySQLGameOperations.GetInstance();
        mySQLUserOperations = MySQLUserOperations.GetInstance();
    }

    public static GameManager getInstance() throws Exception {
        if (instance == null)
            instance = new GameManager();
        return instance;
    }

    public boolean addGame(String userId, String gameTableName) throws EmailNotFoundException, SQLException {
        String playerName = mySQLUserOperations.getName(userId);
        String playerEmail = mySQLUserOperations.getEmail(userId);
        if (!(gameNameExists(gameTableName)) && !userHasTable(playerEmail)) {
            int rating = mySQLUserOperations.getRating(userId);
            Game game = new Game(gameTableName, playerName, playerEmail, rating, userId);
            game.setListener(this);
            games.add(game);
            return true;

        }
        return false;

    }

    public LinkedList<Game> getGameTables() {
        return games;
    }

    private boolean gameNameExists(String name) {

        for (Game g : games)
            if (g.getName().equals(name))
                return true;
        return false;

    }

    public Game getGameTableByName(String name) {
        for (Game g : games)
            if (g.getName().equals(name))
                return g;
        return null;
    }

    public Game getTableByCreator(String email) {
        for (Game g : games)
            if (g.getPlayer1().getEmail().equals(email))
                return g;
        return null;
    }

    public boolean joinTable(String userId, String tableName) throws EmailNotFoundException, SQLException {
        Game game = getGameTableByName(tableName);

        if (game != null) {
            String name;
            int rating;

            String email;
            if (!isGuestId(userId)) {
                email = mySQLUserOperations.getEmail(userId);
                name = mySQLUserOperations.getName(userId);
                rating = mySQLUserOperations.getRating(userId);
            }
            else {
                email = "Guest";
                name = "Guest";
                rating = 1;

            }
            return game.joinPlayer(name, email, rating, userId);
        }

        return false;

    }

    public Game makeMove(Position from, Position to, String gameTableName) throws SQLException, Exception {
        Game game = getGameTableByName(gameTableName);
        game.move(from, to);
        if (game.isGameFinished()) {
        }

        return game;

    }

    public void deleteUserTable(String email) {

        Game game = getTableByCreator(email);
        if (game != null)
            games.remove(game);
    }

    public void deleteTable(String name) {

        Game game = getGameTableByName(name);
        if (game != null) {
            games.remove(game);
        }
    }

    private boolean userHasTable(String email) {

        for (Game game : games) {
            if (game.getPlayer1().getEmail().equals(email))
                return true;


        }
        return false;
    }

    private boolean isGuestId(String userId) {
        if (userId.length() < SessionAttributes.GUEST_ID.length())
            return false;
        String temp = userId.substring(0, SessionAttributes.GUEST_ID.length());
        if (temp.equals(SessionAttributes.GUEST_ID))
            return true;
        return false;
    }

    private void updatePlayerRating(int winnerId) throws SQLException, Exception {

        UserManager userManager = UserManager.getInstance();

        int rating = userManager.getRating("" + winnerId);
        rating = rating + 1;
        userManager.updateRating("" + winnerId, rating);

    }

    @Override
    public void onGameFinished(final Game game) throws SQLException, Exception {

        boolean isGuest = false;
        int player1Id = Integer.parseInt(game.getPlayer1().getId());
        int Player2Id;
        int winnerId;
        game.setGameFinished(true);
        if (game.getPlayer2().getEmail().equals("Guest"))
            isGuest = true;
        if (isGuest)
            Player2Id = 0;
        else
            Player2Id = Integer.parseInt(game.getPlayer2().getId());

        if (game.getWinner() == game.getPlayer2()) {
            winnerId = Player2Id;
        }
        else
            winnerId = player1Id;



        if (winnerId!=0) {
            updatePlayerRating(winnerId);
        }

        GameTable gameTable = new GameTable(player1Id, Player2Id,
                winnerId, game.getCreationDate(), game.getTerminationDate(), isGuest);

        mySqlGameOperations.registerGameTable(gameTable);



        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                games.remove(game);
            }
        }, 5000);



    }

    public long getRemainingTime(String gameTableName) {
        Game game = getGameTableByName(gameTableName);
        long res = game.getRemainingTime();
        return res;
    }
}
